package com.codeyang.listener;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.codeyang.constant.QueueConstant;
import com.codeyang.domain.Order;
import com.codeyang.domain.OrderItem;
import com.codeyang.feign.OrderPayFeign;
import com.codeyang.feign.OrderProdFeign;
import com.codeyang.mapper.OrderItemMapper;
import com.codeyang.mapper.OrderMapper;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 描述: 死信队列监听
 *
 * @author CodeYang_Site
 * @version 2021/6/1 19:18
 */
@Component
@Slf4j
public class DeadQueueListener {


    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderItemMapper orderItemMapper;

    @Autowired
    private OrderProdFeign orderProdFeign;

    @Autowired
    private RabbitTemplate rabbitTemplate;


    @Autowired
    private OrderPayFeign orderPayFeign;

    /**
     * 监听订单的死信队列
     * 处理死信队列里的信息内容
     * 订单未支付就在这里做回滚操作
     * <p>
     * step:
     * 根据订单编号
     * 1 查看订单状态,看是否已经支付
     * 2 未支付
     * 3 加库存-回滚库存 mysql es
     * 4 删除orderItem 记录
     * 5
     *
     * @param message
     * @param channel
     */
    @RabbitListener(queues = QueueConstant.ORDER_DEAD_QUEUE, concurrency = "3-5")
    public void handlerDeadQueue(Message message, Channel channel) {
        log.info("有订单消息进来了");
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        String orderNumber = new String(message.getBody());
        //1.根据订单编号查询订单状态
        try {
            Order order = orderMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNumber, orderNumber));
            if (ObjectUtils.isEmpty(order)) {
                //订单不存在,人工通知技术|记录这个日志
                log.error("订单{}不存在", JSON.toJSONString(order));
                //签收消息
                channel.basicAck(deliveryTag, false);
                return;
            }

            //订单存在查看订单状态
            Integer isPayed = order.getIsPayed();
            if (isPayed.equals(1)) {
                //已经支付了
                //签收消息
                channel.basicAck(deliveryTag, false);
                return;
            }
            //没有支付,主菜来了 回滚数据
            //TODO 还是要去支付宝做一次 回查,因为有可能分布式场景下,各种原因导致MYSQL没有写
            Boolean aBoolean = orderPayFeign.confirmPayStatus(orderNumber);
            if (aBoolean) {
                //交易成功,修改订单状态
                order.setStatus(2);
                order.setUpdateTime(new Date());
                order.setIsPayed(1);
                orderMapper.updateById(order);
                channel.basicAck(deliveryTag, false);
            }
            //确实没有支付-支付失败
            //修改订单状态
            order.setStatus(6);
            order.setUpdateTime(new Date());
            order.setCloseType(1);  //设置订单关闭原因  逻辑删除标志?
            //不会真的删除订单表 和 删除订单条目数据,只是回滚库存等操作
            int i = orderMapper.updateById(order);
            if (i > 0) {
                //1.回滚库存
                //2.向查询出来订单条目 orderItem
                List<OrderItem> orderItems = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItem>()
                        .eq(OrderItem::getOrderNumber, orderNumber)
                );
                //2-1 组装数据集合  prodsMap skusMap 大集合包装一下
                Map<Long, Integer> prodsMap = new HashMap<>();
                Map<Long, Integer> skusMap = new HashMap<>();
                Map<String, Map<Long, Integer>> data = new HashMap<>();
                //2-2 遍历数据 组装数据
                orderItems.forEach(orderItem -> {
                    Long prodId = orderItem.getProdId();
                    Long skuId = orderItem.getSkuId();
                    Integer count = orderItem.getProdCount();
                    //组装 修改id的数量
                    skusMap.put(skuId, count);
                    if (prodsMap.containsKey(prodId)) {
                        prodsMap.put(prodId, prodsMap.get(prodId) + count);
                    }
                    prodsMap.put(prodId, count);
                });
                data.put("prod", prodsMap);
                data.put("sku", skusMap);
                //3.远程调用,修改MYSQL库存
                orderProdFeign.changeStock(data);
                //4.回滚es库存  proIdsMap
                rabbitTemplate.convertAndSend(QueueConstant.PROD_CHANGE_QUEUE, JSON.toJSONString(prodsMap));
                //签收
                channel.basicAck(deliveryTag, false);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("订单--消息被签收了");
        return;
    }

}
